import Down
import UIKit

public class MarkdownParser {
    private let down: Down
    private let imageBaseURL: URL?
    private let containerWidth: CGFloat
    private let customTagHandler = CustomTagHandler()
    private let theme: MarkdownTheme
    
    public init(markdownString: String, containerWidth: CGFloat, imageBaseURL: URL? = nil, theme: MarkdownTheme = .light) {
        self.down = Down(markdownString: markdownString)
        self.containerWidth = containerWidth
        self.imageBaseURL = imageBaseURL
        self.theme = theme
    }
    
    public func parse() throws -> NSAttributedString {
        let attributedString = try down.toAttributedString(stylesheet: defaultStylesheet)
        let withCustomTags = processCustomTags(in: attributedString)
        let withNowcoderTags = processNowcoderTags(in: withCustomTags)
        let withCodeBlocks = processCodeBlocks(in: withNowcoderTags)
        processImages(in: withCodeBlocks)
        return withCodeBlocks
    }
    
    private func processImages(in attributedString: NSAttributedString) -> NSAttributedString {
        let mutableString = NSMutableAttributedString(attributedString: attributedString)
        mutableString.enumerateAttribute(.attachment, in: NSRange(location: 0, length: mutableString.length)) { value, range, _ in
            guard let attachment = value as? NSTextAttachment else { return }
            
            if let imageURL = attachment.fileWrapper?.preferredFilename.flatMap({ URL(string: $0) }) {
                let finalURL = imageBaseURL?.appendingPathComponent(imageURL.absoluteString) ?? imageURL
                print("🖼️ 开始处理图片: \(finalURL)")
                
                // 创建占位图
                let placeholderImage = UIImage(systemName: "photo")?
                    .withTintColor(theme.image.placeholderColor, renderingMode: .alwaysOriginal) ?? UIImage()
                print("📍 创建占位图: size = \(placeholderImage.size)")
                
                // 创建新的附件
                let newAttachment = NSTextAttachment()
                newAttachment.image = placeholderImage
                
                // 计算图片显示尺寸
                let maxWidth = min(theme.image.maxWidth, containerWidth - 32)
                let placeholderSize = CGSize(width: maxWidth, height: maxWidth * 0.6)
                print("📐 计算占位图尺寸: maxWidth = \(maxWidth), size = \(placeholderSize)")
                
                // 设置初始大小
                newAttachment.bounds = CGRect(
                    x: 0,
                    y: 0,
                    width: placeholderSize.width,
                    height: placeholderSize.height
                )
                
                // 替换原附件
                let attachmentString = NSAttributedString(attachment: newAttachment)
                mutableString.replaceCharacters(in: range, with: attachmentString)
                print("🔄 替换原附件为占位图")
                
                // 使用ImageLoader加载图片
                print("⬇️ 开始加载图片: \(finalURL)")
                ImageLoader.shared.loadImage(
                    from: finalURL,
                    placeholder: placeholderImage
                ) { [weak newAttachment, weak self] result in
                    guard let self else {
                        print("❌ 图片加载回调时 self 已释放")
                        return
                    }
                    
                    switch result {
                    case .success(let image):
                        print("✅ 图片加载成功: \(finalURL)")
                        print("📊 原始图片尺寸: \(image.size)")
                        
                        DispatchQueue.main.async {
                            // 计算实际显示大小
                            let imageSize = image.size
                            let aspectRatio = imageSize.width / imageSize.height
                            
                            var targetSize = CGSize(
                                width: maxWidth,
                                height: maxWidth / aspectRatio
                            )
                            
                            // 如果图片原始尺寸小于最大宽度，使用原始尺寸
                            if imageSize.width < maxWidth {
                                targetSize = imageSize
                                print("📏 使用原始尺寸: \(targetSize)")
                            } else {
                                print("📏 缩放到目标尺寸: \(targetSize)")
                            }
                            
                            // 更新附件大小和图片
                            newAttachment?.bounds = CGRect(
                                x: 0,
                                y: 0,
                                width: targetSize.width,
                                height: targetSize.height
                            )
                            
                            // 根据主题设置圆角
                            if self.theme.image.cornerRadius > 0 {
                                print("⭕️ 添加圆角: \(self.theme.image.cornerRadius)")
                                let renderer = UIGraphicsImageRenderer(size: targetSize)
                                let roundedImage = renderer.image { context in
                                    let rect = CGRect(origin: .zero, size: targetSize)
                                    let path = UIBezierPath(
                                        roundedRect: rect,
                                        cornerRadius: self.theme.image.cornerRadius
                                    )
                                    
                                    context.cgContext.addPath(path.cgPath)
                                    context.cgContext.clip()
                                    
                                    image.draw(in: rect)
                                }
                                newAttachment?.image = roundedImage
                                print("✨ 圆角处理完成")
                            } else {
                                newAttachment?.image = image
                                print("✨ 直接使用原图")
                            }
                            
                            // 通知布局更新
                            NotificationCenter.default.post(
                                name: NSTextStorage.didProcessEditingNotification,
                                object: mutableString
                            )
                            print("🔄 发送布局更新通知")
                        }
                        
                    case .failure(let error):
                        print("❌ 图片加载失败: \(finalURL)")
                        print("💥 错误信息: \(error)")
                    }
                }
            }
        }
        
        return mutableString
    }
    
    private func processCodeBlocks(in attributedString: NSAttributedString) -> NSAttributedString {
        let mutableString = NSMutableAttributedString(attributedString: attributedString)
        
        // 查找所有代码块
        let pattern = "```([\\w-]*)?\\n([\\s\\S]*?)```"
        let regex = try? NSRegularExpression(pattern: pattern, options: [])
        let range = NSRange(location: 0, length: mutableString.length)
        
        // 从后向前替换，避免位置变化
        regex?.matches(in: mutableString.string, options: [], range: range)
            .reversed()
            .forEach { match in
                let languageRange = match.range(at: 1)
                let codeRange = match.range(at: 2)
                
                if languageRange.location != NSNotFound && codeRange.location != NSNotFound {
                    let language = (mutableString.string as NSString).substring(with: languageRange)
                    let code = (mutableString.string as NSString).substring(with: codeRange)
                    
                    // 创建代码块视图
                    let codeBlockView = CodeBlockView(language: language, code: code)
                    
                    // 创建附件
                    let attachment = NSTextAttachment()
                    attachment.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width - 32, height: 60) // 临时高度
                    attachment.image = codeBlockView.asImage()
                    
                    // 替换原文本
                    let attachmentString = NSAttributedString(attachment: attachment)
                    mutableString.replaceCharacters(in: match.range, with: attachmentString)
                }
            }
        
        return mutableString
    }
    
    private func processNowcoderTags(in attributedString: NSAttributedString) -> NSAttributedString {
        let mutableString = NSMutableAttributedString(attributedString: attributedString)
        
        // 查找所有 nowcoder span 标签
        let pattern = "<span[^>]*class=\"[^\"]*nowcoder[^\"]*\"[^>]*>(.*?)</span>"
        let regex = try? NSRegularExpression(pattern: pattern, options: [.dotMatchesLineSeparators])
        let range = NSRange(location: 0, length: mutableString.length)
        
        // 从后向前替换，避免位置变化
        regex?.matches(in: mutableString.string, options: [], range: range)
            .reversed()
            .forEach { match in
                // 解析标签属性
                let tagRange = match.range(at: 0)
                let contentRange = match.range(at: 1)
                
                if tagRange.location != NSNotFound && contentRange.location != NSNotFound {
                    let tagString = (mutableString.string as NSString).substring(with: tagRange)
                    let content = (mutableString.string as NSString).substring(with: contentRange)
                    
                    // 提取属性
                    let attributes = extractAttributes(from: tagString)
                    
                    // 创建自定义视图
                    if let customView = NowcoderTagHandler.createView(attributes: attributes, content: content) {
                        // 创建附件
                        let attachment = NSTextAttachment()
                        attachment.bounds = customView.bounds
                        attachment.image = customView.asImage()
                        
                        // 替换原文本
                        let attachmentString = NSAttributedString(attachment: attachment)
                        mutableString.replaceCharacters(in: tagRange, with: attachmentString)
                    }
                }
            }
        
        return mutableString
    }
    
    private func extractAttributes(from tag: String) -> [String: String] {
        var attributes: [String: String] = [:]
        
        // 匹配属性
        let pattern = "([a-zA-Z-]+)=\"([^\"]*)\""
        let regex = try? NSRegularExpression(pattern: pattern, options: [])
        let range = NSRange(location: 0, length: tag.count)
        
        regex?.matches(in: tag, options: [], range: range).forEach { match in
            if match.numberOfRanges == 3 {
                let keyRange = match.range(at: 1)
                let valueRange = match.range(at: 2)
                
                let key = (tag as NSString).substring(with: keyRange)
                let value = (tag as NSString).substring(with: valueRange)
                
                attributes[key] = value
            }
        }
        
        return attributes
    }
    
    private func processCustomTags(in attributedString: NSAttributedString) -> NSAttributedString {
        let mutableString = NSMutableAttributedString(attributedString: attributedString)
        
        // Match custom tags
        let pattern = "<[^>]+>[^<]*</[^>]+>"
        let regex = try? NSRegularExpression(pattern: pattern)
        let range = NSRange(location: 0, length: mutableString.length)
        
        // Process matches from end to start to avoid position changes
        regex?.matches(in: mutableString.string, options: [], range: range)
            .reversed()
            .forEach { match in
                let tagRange = match.range
                let tagString = (mutableString.string as NSString).substring(with: tagRange)
                
                if let tagInfo = customTagHandler.parseTag(from: tagString),
                   let customView = customTagHandler.createView(for: tagInfo) {
                    // Create attachment
                    let attachment = NSTextAttachment()
                    attachment.bounds = customView.bounds
                    attachment.image = customView.asImage()
                    
                    // Replace original text
                    let attachmentString = NSAttributedString(attachment: attachment)
                    mutableString.replaceCharacters(in: tagRange, with: attachmentString)
                }
            }
        
        return mutableString
    }
    
    // 默认样式配置
    private var defaultStylesheet: String {
        return """
        * {
            font-family: -apple-system;
            font-size: \(theme.base.font.pointSize)px;
            color: \(theme.base.textColor.cssColor);
            line-height: \(theme.base.lineHeightMultiple);
        }
        
        h1 {
            font-size: \(theme.heading.h1.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h1.textColor.cssColor);
            margin-bottom: \(theme.heading.h1.paragraphSpacing)px;
        }
        
        h2 {
            font-size: \(theme.heading.h2.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h2.textColor.cssColor);
            margin-bottom: \(theme.heading.h2.paragraphSpacing)px;
        }
        
        h3 {
            font-size: \(theme.heading.h3.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h3.textColor.cssColor);
            margin-bottom: \(theme.heading.h3.paragraphSpacing)px;
        }
        
        h4 {
            font-size: \(theme.heading.h4.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h4.textColor.cssColor);
            margin-bottom: \(theme.heading.h4.paragraphSpacing)px;
        }
        
        h5 {
            font-size: \(theme.heading.h5.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h5.textColor.cssColor);
            margin-bottom: \(theme.heading.h5.paragraphSpacing)px;
        }
        
        h6 {
            font-size: \(theme.heading.h6.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h6.textColor.cssColor);
            margin-bottom: \(theme.heading.h6.paragraphSpacing)px;
        }
        
        code {
            font-family: Menlo;
            background-color: \(theme.code.inlineBackgroundColor.cssColor);
            color: \(theme.code.inlineTextColor.cssColor);
            padding: \(theme.code.codeBlockPadding.top)px \(theme.code.codeBlockPadding.right)px \(theme.code.codeBlockPadding.bottom)px \(theme.code.codeBlockPadding.left)px;
            border-radius: \(theme.code.cornerRadius)px;
        }
        
        pre {
            background-color: \(theme.code.backgroundColor.cssColor);
            padding: \(theme.code.insets.top)px \(theme.code.insets.right)px \(theme.code.insets.bottom)px \(theme.code.insets.left)px;
            border-radius: \(theme.code.cornerRadius)px;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: \(theme.code.borderWidth)px solid \(theme.code.borderColor.cssColor);
        }
        
        blockquote {
            background-color: \(theme.quote.backgroundColor.cssColor);
            border-left: \(theme.quote.borderWidth)px solid \(theme.quote.borderColor.cssColor);
            padding: \(theme.quote.insets.top)px \(theme.quote.insets.right)px \(theme.quote.insets.bottom)px \(theme.quote.insets.left)px;
            color: \(theme.quote.textColor.cssColor);
            margin: \(theme.base.paragraphSpacing)px 0;
        }
        
        ul, ol {
            margin: \(theme.list.itemSpacing)px 0;
            padding-left: \(theme.list.indentationWidth)px;
        }
        
        li {
            margin: \(theme.list.itemSpacing)px 0;
            color: \(theme.list.textColor.cssColor);
        }
        
        table {
            border-collapse: collapse;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: 1px solid \(theme.table.borderColor.cssColor);
        }
        
        th {
            background-color: \(theme.table.headerBackgroundColor.cssColor);
            color: \(theme.table.headerTextColor.cssColor);
            padding: 8px;
            border: 1px solid \(theme.table.borderColor.cssColor);
        }
        
        td {
            background-color: \(theme.table.cellBackgroundColor.cssColor);
            color: \(theme.table.cellTextColor.cssColor);
            padding: 8px;
            border: 1px solid \(theme.table.borderColor.cssColor);
        }
        
        a {
            color: \(theme.link.defaultColors.textColor.cssColor);
            text-decoration-color: \(theme.link.defaultColors.underlineColor.cssColor);
            background-color: \(theme.link.defaultColors.backgroundColor.cssColor);
        }
        
        img {
            max-width: 100%;
            height: auto;
            margin: \(theme.base.paragraphSpacing)px 0;
        }
        
        p {
            margin: \(theme.paragraph.insets.top)px 0 \(theme.paragraph.insets.bottom)px 0;
            line-height: \(theme.paragraph.lineHeightMultiple);
            text-indent: \(theme.paragraph.firstLineHeadIndent)px;
            color: \(theme.paragraph.textColor.cssColor);
        }
        """
    }
    
    private func generateStylesheet(theme: MarkdownTheme) -> String {
        return """
        \(baseStylesheet(theme))
        \(htmlTagStylesheet(theme))
        """
    }
    
    private func baseStylesheet(_ theme: MarkdownTheme) -> String {
        return """
        * {
            font-family: -apple-system;
            font-size: \(theme.text.font.pointSize)px;
            color: \(theme.text.textColor.cssColor);
            line-height: \(theme.text.lineHeightMultiple);
        }
        
        h1 {
            font-size: \(theme.heading.h1.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h1.textColor.cssColor);
            margin-bottom: \(theme.heading.h1.paragraphSpacing)px;
        }
        
        h2 {
            font-size: \(theme.heading.h2.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h2.textColor.cssColor);
            margin-bottom: \(theme.heading.h2.paragraphSpacing)px;
        }
        
        h3 {
            font-size: \(theme.heading.h3.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h3.textColor.cssColor);
            margin-bottom: \(theme.heading.h3.paragraphSpacing)px;
        }
        
        h4 {
            font-size: \(theme.heading.h4.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h4.textColor.cssColor);
            margin-bottom: \(theme.heading.h4.paragraphSpacing)px;
        }
        
        h5 {
            font-size: \(theme.heading.h5.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h5.textColor.cssColor);
            margin-bottom: \(theme.heading.h5.paragraphSpacing)px;
        }
        
        h6 {
            font-size: \(theme.heading.h6.font.pointSize)px;
            font-weight: bold;
            color: \(theme.heading.h6.textColor.cssColor);
            margin-bottom: \(theme.heading.h6.paragraphSpacing)px;
        }
        
        code {
            font-family: \(theme.code.font.familyName);
            background-color: \(theme.code.backgroundColor.cssColor);
            color: \(theme.code.textColor.cssColor);
            padding: \(theme.code.codeBlockPadding.top)px \(theme.code.codeBlockPadding.right)px \(theme.code.codeBlockPadding.bottom)px \(theme.code.codeBlockPadding.left)px;
            border-radius: \(theme.code.cornerRadius)px;
        }
        
        pre {
            background-color: \(theme.code.backgroundColor.cssColor);
            padding: \(theme.code.insets.top)px \(theme.code.insets.right)px \(theme.code.insets.bottom)px \(theme.code.insets.left)px;
            border-radius: \(theme.code.cornerRadius)px;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: \(theme.code.borderWidth)px solid \(theme.code.borderColor.cssColor);
        }
        
        blockquote {
            background-color: \(theme.quote.backgroundColor.cssColor);
            border-left: \(theme.quote.borderWidth)px solid \(theme.quote.borderColor.cssColor);
            padding: \(theme.quote.insets.top)px \(theme.quote.insets.right)px \(theme.quote.insets.bottom)px \(theme.quote.insets.left)px;
            color: \(theme.quote.textColor.cssColor);
            margin: \(theme.base.paragraphSpacing)px 0;
        }
        
        ul, ol {
            margin: \(theme.list.itemSpacing)px 0;
            padding-left: \(theme.list.indentationWidth)px;
        }
        
        li {
            margin: \(theme.list.itemSpacing)px 0;
            color: \(theme.list.textColor.cssColor);
        }
        
        table {
            border-collapse: collapse;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: 1px solid \(theme.table.borderColor.cssColor);
        }
        
        th {
            background-color: \(theme.table.headerBackgroundColor.cssColor);
            color: \(theme.table.headerTextColor.cssColor);
            padding: 8px;
            border: 1px solid \(theme.table.borderColor.cssColor);
        }
        
        td {
            background-color: \(theme.table.cellBackgroundColor.cssColor);
            color: \(theme.table.cellTextColor.cssColor);
            padding: 8px;
            border: 1px solid \(theme.table.borderColor.cssColor);
        }
        
        a {
            color: \(theme.link.defaultColors.textColor.cssColor);
            text-decoration-color: \(theme.link.defaultColors.underlineColor.cssColor);
            background-color: \(theme.link.defaultColors.backgroundColor.cssColor);
        }
        
        img {
            max-width: 100%;
            height: auto;
            margin: \(theme.base.paragraphSpacing)px 0;
        }
        
        p {
            margin: \(theme.paragraph.insets.top)px 0 \(theme.paragraph.insets.bottom)px 0;
            line-height: \(theme.paragraph.lineHeightMultiple);
            text-indent: \(theme.paragraph.firstLineHeadIndent)px;
            color: \(theme.paragraph.textColor.cssColor);
        }
        """
    }
    
    private func htmlTagStylesheet(_ theme: MarkdownTheme) -> String {
        return """
        /* HTML标签样式 */
        sup {
            font-size: 0.8em;
            vertical-align: super;
        }
        
        sub {
            font-size: 0.8em;
            vertical-align: sub;
        }
        
        mark {
            background-color: \(theme.text.backgroundColor.cssColor);
            color: \(theme.text.textColor.cssColor);
            padding: 0 2px;
            border-radius: 2px;
        }
        
        ruby {
            ruby-position: over;
        }
        
        rt {
            font-size: 0.6em;
            color: \(theme.text.textColor.cssColor);
        }
        
        /* 自定义类样式 */
        .warning {
            background-color: \(theme.alert.warningConfig.backgroundColor.cssColor);
            color: \(theme.alert.warningConfig.textColor.cssColor);
            padding: \(theme.alert.padding.top)px \(theme.alert.padding.right)px \(theme.alert.padding.bottom)px \(theme.alert.padding.left)px;
            border-radius: \(theme.alert.cornerRadius)px;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: \(theme.alert.borderWidth)px solid \(theme.alert.warningConfig.borderColor.cssColor);
        }
        
        .info {
            background-color: \(theme.alert.infoConfig.backgroundColor.cssColor);
            color: \(theme.alert.infoConfig.textColor.cssColor);
            padding: \(theme.alert.padding.top)px \(theme.alert.padding.right)px \(theme.alert.padding.bottom)px \(theme.alert.padding.left)px;
            border-radius: \(theme.alert.cornerRadius)px;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: \(theme.alert.borderWidth)px solid \(theme.alert.infoConfig.borderColor.cssColor);
        }
        
        .success {
            background-color: \(theme.alert.successConfig.backgroundColor.cssColor);
            color: \(theme.alert.successConfig.textColor.cssColor);
            padding: \(theme.alert.padding.top)px \(theme.alert.padding.right)px \(theme.alert.padding.bottom)px \(theme.alert.padding.left)px;
            border-radius: \(theme.alert.cornerRadius)px;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: \(theme.alert.borderWidth)px solid \(theme.alert.successConfig.borderColor.cssColor);
        }
        
        .error {
            background-color: \(theme.alert.errorConfig.backgroundColor.cssColor);
            color: \(theme.alert.errorConfig.textColor.cssColor);
            padding: \(theme.alert.padding.top)px \(theme.alert.padding.right)px \(theme.alert.padding.bottom)px \(theme.alert.padding.left)px;
            border-radius: \(theme.alert.cornerRadius)px;
            margin: \(theme.base.paragraphSpacing)px 0;
            border: \(theme.alert.borderWidth)px solid \(theme.alert.errorConfig.borderColor.cssColor);
        }
        """
    }
} 
